#include "data_manager.h"
#include "mastery_evaluator.h"
#include <algorithm> // For string cleanup
#include <ctime> // For time operations
#include <iomanip> // For setfill, setw, fixed, setprecision
#include <iostream>
#include <limits> // For cin.ignore
#include <sstream>

using namespace std;

// --- Helper Functions ---

/**
 * @brief 辅助函数：将逗号分隔的字符串转为 Topics 向量。
 * @param s 逗号分隔的字符串
 * @return 专题名称向量
 */
vector<string> stringToTopics(const string& s)
{
    vector<string> topics;
    stringstream ss(s);
    string item;
    while (getline(ss, item, ',')) {
        // 清理首尾空格
        item.erase(0, item.find_first_not_of(" \t\n\r\f\v"));
        item.erase(item.find_last_not_of(" \t\n\r\f\v") + 1);
        if (!item.empty()) {
            topics.push_back(item);
        }
    }
    return topics;
}

/**
 * @brief 辅助函数：获取当前日期时间字符串 (YYYY-MM-DD HH:MM:SS)
 * @return 当前时间的字符串表示
 */
string getCurrentDateTime()
{
    time_t now = time(0);
    tm* ltm = localtime(&now);
    stringstream ss;
    ss << (1900 + ltm->tm_year) << "-"
       << setfill('0') << setw(2) << (1 + ltm->tm_mon) << "-"
       << setfill('0') << setw(2) << ltm->tm_mday << " "
       << setfill('0') << setw(2) << ltm->tm_hour << ":"
       << setfill('0') << setw(2) << ltm->tm_min << ":"
       << setfill('0') << setw(2) << ltm->tm_sec;
    return ss.str();
}

// --- Main CLI Logic ---

void showHelp()
{
    cout << "\n--- Informatics Tutor CLI Help ---\n";
    cout << "init: 设置目标 Rating (TargetCFRating)\n";
    cout << "log add: 添加题目记录 (交互式输入)\n";
    cout << "log update <ID/Title>: 更新题目复习记录 (支持 ID 或标题)\n"; // 帮助信息更新
    cout << "eval show-equivalent: 显示整体平均掌握度\n";
    cout << "eval show-topic-ratings: 显示专题平均掌握度\n";
    cout << "plan generate: 生成学习计划（复习+新题推荐）\n";
    cout << "exit: 保存并退出\n";
    cout << "help: 显示帮助\n";
    cout << "---------------------------------\n";
}

int main()
{
    // 实例化 DataManager 时，其构造函数会自动调用 loadData()
    DataManager dataManager;
    // 实例化 MasteryEvaluator，它依赖 dataManager 实例
    MasteryEvaluator evaluator(dataManager);

    cout << "Welcome to Informatics Study Assistant (Current Target: " << dataManager.config.TargetCFRating << ", Equivalent CF: " << dataManager.config.CurrentCFEquivalent << ")\n";
    string command;
    showHelp();

    while (true) {
        cout << "\n> ";
        string fullLine;
        // 使用 getline 确保能读取包含空格的输入
        if (!getline(cin, fullLine))
            break;

        stringstream ss(fullLine);
        ss >> command;

        if (command.empty())
            continue;

        if (command == "exit") {
            dataManager.saveData();
            break;
        } else if (command == "log") {
            string subCommand;
            ss >> subCommand;

            if (subCommand == "add") {
                Problem newProblem;

                // 1. Problem ID (Auto-generated for simplicity)
                newProblem.ProblemID = "CF-" + to_string(dataManager.problems.size() + 1);

                cout << "--- Adding New Problem ---\n";

                // 2. Title
                cout << "Enter Problem Title: ";
                string title;
                getline(cin, title);
                newProblem.Title = title;

                // 3. Difficulty
                cout << "Enter Problem Difficulty Rating (e.g., 2000): ";
                int difficulty;
                if (!(cin >> difficulty)) {
                    cout << "Invalid difficulty. Aborting log.\n";
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    continue;
                }
                newProblem.Difficulty = difficulty;
                cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Clear the rest of the line

                // 4. Topics
                cout << "Enter Topics (comma-separated, e.g., DP,Graph): ";
                string topicsString;
                getline(cin, topicsString);
                newProblem.Topics = stringToTopics(topicsString);

                // 检查并添加新的专题到 DataManager
                for (const auto& topic : newProblem.Topics) {
                    if (dataManager.topics.find(topic) == dataManager.topics.end()) {
                        dataManager.topics[topic].Name = topic;
                        dataManager.topics[topic].TopicCFRating = 500; // 默认初始掌握度 0.50 * 1000
                        cout << "New topic '" << topic << "' added to dictionary.\n";
                    }
                }

                // 5. TimeSpentMinutes
                cout << "Enter Time Spent (minutes): ";
                int timeSpent;
                if (!(cin >> timeSpent)) {
                    cout << "Invalid time. Aborting log.\n";
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    continue;
                }
                newProblem.TimeSpentMinutes = timeSpent;

                // 6. UsedSolution
                cout << "Did you use a solution/hint (1 for Yes, 0 for No)? ";
                int usedSolutionInt;
                if (!(cin >> usedSolutionInt) || (usedSolutionInt != 0 && usedSolutionInt != 1)) {
                    cout << "Invalid input. Assuming 0 (No).\n";
                    usedSolutionInt = 0;
                }
                newProblem.UsedSolution = (usedSolutionInt == 1);

                // 7. AttemptCount
                cout << "Enter number of attempts (e.g., 1): ";
                int attemptCount;
                if (!(cin >> attemptCount) || attemptCount < 1) {
                    cout << "Invalid attempt count. Assuming 1.\n";
                    attemptCount = 1;
                }
                newProblem.AttemptCount = attemptCount;
                cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Clear the rest of the line

                // 8. Omissions
                cout << "Enter Omissions/Notes (e.g., Forgot to check boundary conditions): ";
                string omissions;
                getline(cin, omissions);
                newProblem.Omissions = omissions;

                // 9. DateSolved (Current Time)
                newProblem.DateSolved = getCurrentDateTime();

                // 计算 MasteryScore
                evaluator.calculateProblemMastery(newProblem);

                // 将题目添加到数据集中
                dataManager.problems[newProblem.ProblemID] = newProblem;

                cout << "\nAdded problem " << newProblem.ProblemID << " (" << newProblem.Title << "). MasteryScore: " << newProblem.MasteryScore << endl;
                cout << "Run 'eval show-equivalent' to see your overall mastery score.\n";
            }

            // --- LOG UPDATE: 更新复习情况 (支持 ID/Title 查找，覆盖旧性能数据) ---
            else if (subCommand == "update") {
                string searchInput;
                // 读取剩下的全部内容作为题目 ID 或标题
                getline(ss >> ws, searchInput);

                if (searchInput.empty()) {
                    cout << "错误: 请指定要更新的题目 ID 或标题。\n";
                    continue;
                }

                Problem* targetProblem = nullptr;
                string foundId;

                // 1. 尝试按 ProblemID 精确查找 (e.g., CF-1)
                auto it_id = dataManager.problems.find(searchInput);
                if (it_id != dataManager.problems.end()) {
                    targetProblem = &it_id->second;
                    foundId = searchInput;
                } else {
                    // 2. 尝试按 Title 精确查找 (用户要求的查找方式)
                    for (auto& pair : dataManager.problems) {
                        // 使用用户输入与 Problem Title 进行匹配
                        if (pair.second.Title == searchInput) {
                            targetProblem = &pair.second;
                            foundId = pair.first;
                            break;
                        }
                    }
                }

                if (targetProblem == nullptr) {
                    cout << "错误：未找到题目 ID 或标题 [" << searchInput << "] 的记录。请使用精确 ID 或完整标题。\n";
                    continue;
                }

                Problem& p = *targetProblem; // 获取题目的可修改引用
                string problemId = foundId;

                // 需要设置iomanip的精度，因为这里直接使用了cout
                cout << fixed << setprecision(2);
                cout << "--- 更新题目 [" << problemId << " - " << p.Title << "] 的复习状态 ---\n";
                cout << "上次状态: MasteryScore: " << p.MasteryScore
                     << ", 看了题解: " << (p.UsedSolution ? "是" : "否")
                     << ", 总用时: " << p.TimeSpentMinutes << " min\n"
                     << "历史提交次数: " << p.AttemptCount << "\n";

                // *** 询问本次“重新解决”的全新数据，覆盖旧的性能指标 ***

                int currentReviewTime;
                cout << "本次独立解决所需总用时 (分钟，将覆盖旧用时): ";
                if (!(cin >> currentReviewTime) || currentReviewTime < 0) {
                    cout << "输入无效。中止更新。\n";
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    continue;
                }

                int currentAttemptCount;
                cout << "本次独立解决所需总尝试次数 (将覆盖旧次数): ";
                if (!(cin >> currentAttemptCount) || currentAttemptCount < 1) {
                    cout << "输入无效。中止更新。\n";
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    continue;
                }
                cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 清理输入流

                char solvedIndependentlyChar;
                cout << "本次是否独立解决 (y/n): ";
                if (!(cin >> solvedIndependentlyChar)) {
                    cout << "输入无效。中止更新。\n";
                    cin.clear();
                    cin.ignore(numeric_limits<streamsize>::max(), '\n');
                    continue;
                }
                bool solvedNow = (solvedIndependentlyChar == 'y' || solvedIndependentlyChar == 'Y');
                cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 清理输入流

                // 1. 覆盖用时
                p.TimeSpentMinutes = currentReviewTime;

                // 2. 覆盖尝试次数
                p.AttemptCount = currentAttemptCount;

                // 3. 更新解题状态和日期
                if (solvedNow) {
                    p.UsedSolution = false;
                    cout << "状态更新: 标记为 '最终独立解决'。\n";
                } else {
                    // 如果本次未能独立解决，UsedSolution 保持或设置为 true，MasteryScore 将降低
                    cout << "状态更新: 未独立解决，保持原状态 (MasteryScore 将基于新数据重新计算)。\n";
                }
                p.DateSolved = getCurrentDateTime(); // 更新最近解决时间

                // 4. 重新计算 MasteryScore
                evaluator.calculateProblemMastery(p);

                // 5. 保存数据
                dataManager.saveData();
                cout << "\n记录 [" << problemId << "] 已更新。新的性能指标已覆盖旧记录。请运行 'eval show-equivalent' 查看掌握度变化。\n";

            } else {
                cout << "Unknown 'log' subcommand.\n";
            }
        } else if (command == "eval") {
            string subCommand;
            ss >> subCommand;
            if (subCommand == "show-equivalent") {
                evaluator.calculateOverallRating();
            } else if (subCommand == "show-topic-ratings") {
                evaluator.calculateTopicRatings();
                cout << "--- Topic Mastery Index (Avg Mastery * 1000) ---\n";
                for (const auto& pair : dataManager.topics) {
                    cout << pair.first << " (" << pair.second.Name << "): " << pair.second.TopicCFRating << endl;
                }
            } else {
                cout << "Unknown 'eval' subcommand.\n";
            }
        } else if (command == "plan") {
            string subCommand;
            ss >> subCommand;
            if (subCommand == "generate") {
                // 在生成计划前先确保掌握度数据是最新的
                evaluator.calculateOverallRating();
                evaluator.calculateTopicRatings();
                evaluator.generateStudyPlan();
            } else {
                cout << "Unknown 'plan' subcommand. Use 'plan generate'.\n";
            }
        } else if (command == "help") {
            showHelp();
        } else if (command == "init") {
            cout << "Current Target Rating is " << dataManager.config.TargetCFRating << ". Enter new target: ";
            int newTarget;
            // 从命令行读取新目标，但要小心处理输入流
            if (cin >> newTarget) {
                dataManager.config.TargetCFRating = newTarget;
                cout << "Target set to " << newTarget << endl;
                // 清理输入流，准备下一次getline
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
            } else {
                cout << "Invalid input (Must be an integer).\n";
                cin.clear();
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
            }
        } else {
            cout << "Unknown command: " << command << ". Type 'help' for commands.\n";
        }
    }

    return 0;
}
